#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sqlite3.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <time.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

#define N 16
#define M 256
#define R 1
#define L 2
#define S 3
#define H 4
#define D 5
#define C 6
#define DATABASE "my.db"

typedef struct{
	char name[N];
	char sex;
	int  age;
	int num;
}MESG;

typedef struct{
	int type;
	char name[N];
	char data[M];
}MSG;
int do_recv_message(int acceptd, sqlite3 *db)
{
	char sqlstr[300];
	char *errmsg;
	recv(acceptd, sqlstr, sizeof(sqlstr), 0);
	printf("%s\n", sqlstr);
	if(sqlite3_exec(db, sqlstr, NULL, NULL, &errmsg) != SQLITE_OK)
	{
		sprintf(sqlstr, "user already exist");
	}
	strcpy(sqlstr, "Ok");
	send(acceptd, sqlstr, sizeof(sqlstr), 0);
	return 0;
}

int do_register(int acceptd, MSG *msg, sqlite3 *db)
{
	char sqlstr[128] = {0};
	char *errmsg;
	sprintf(sqlstr, "insert into usr values('%s', '%s')", msg->name, msg->data);

	if(sqlite3_exec(db, sqlstr, NULL, NULL, &errmsg) != SQLITE_OK)
	{
		sprintf(msg->data, "user %s already exist", msg->name);
	}
	else
	{
		strcpy(msg->data, "OK");
		send(acceptd, msg, sizeof(MSG), 0);
		do_recv_message(acceptd, db);
	}

	return 0;

}

int do_delect_usr(int acceptd, MSG *msg, sqlite3 *db)
{
	char sqlstr[128] = {0};
	char *errmsg;
	sprintf(sqlstr, "delete from message where name = '%s'", msg->name);
	
	if(sqlite3_exec(db, sqlstr, NULL, NULL, &errmsg) != SQLITE_OK)
	{
		sprintf(msg->data, "message %s not", msg->name);
		send(acceptd, msg, sizeof(MSG), 0);
	}

	else
	{
		strcpy(msg->data, "OK");
		send(acceptd, msg, sizeof(MSG), 0);
		return 0;
	}
}
int do_change_usr(int acceptd, MSG *msg, sqlite3 *db)
{
	char *errmsg;
	printf("%s\n", msg->data);
	if(sqlite3_exec(db, msg->data, NULL, NULL, &errmsg) != SQLITE_OK)
	{
		sprintf(msg->data, "user %s is not\n", msg->name);
		send(acceptd, msg, sizeof(MSG), 0);
	}
	else
	{
		strcpy(msg->data,"OK");
		send(acceptd, msg, sizeof(MSG), 0);
		return 0;
	}

}


static int history_callback(void *arg, int f_num, char **f_value, char **f_name)
{
	MSG msg;
	int acceptd = *(int *)arg;
	sprintf(msg.data, "%s : %s, %s : %s, %s : %s",f_name[0], f_value[0], f_name[1], f_value[1], f_name[2],f_value[2]);
	send(acceptd, &msg, sizeof(MSG), 0);
	return 0;
}

int do_search(int acceptd, MSG * msg, sqlite3 *db)
{
	char *errmsg;
	if(sqlite3_exec(db, msg->data, history_callback, (void *)&acceptd,  &errmsg) != SQLITE_OK)
	{
		printf("error %s\n", errmsg);
		sqlite3_free(errmsg);
	}	
	
	strcpy(msg->data, "OK");
	send(acceptd, msg, sizeof(MSG), 0);
	return 0;

}

int do_change_passwd(int acceptd, MSG * msg, sqlite3 *db)
{
	char *errmsg;
	printf("%s", msg->data);
	if(sqlite3_exec(db,msg->data, NULL, NULL, &errmsg) != SQLITE_OK)
	{
		sprintf(msg->data, "user %s is not", msg->name);
		send(acceptd, msg, sizeof(MSG), 0);
	}
	strcpy(msg->data, "OK");
	send(acceptd, msg, sizeof(MSG), 0);
	return 0;

}


int do_login(int acceptd, MSG *msg, sqlite3 *db)
{
	char sqlstr[128] = {0};
	char *errmsg, **result;
	int nrow, ncolum;
	
	sprintf(sqlstr, "select * from usr where name = '%s' and passwd = '%s'", msg->name, msg->data);
	if(sqlite3_get_table(db, sqlstr, &result, &nrow, &ncolum, &errmsg) != SQLITE_OK)
	{
		printf("error %s\n", errmsg);	
	}
	if(nrow == 0)
	{
		strcpy(msg->data, "name or passwd input error");
	}
	else
	{
		strncpy(msg->data, "OK", M);
	}
	send(acceptd, msg, sizeof(MSG), 0);

	return 0;
}


void do_client(int acceptd, sqlite3 *db)
{
	MSG msg;

	while(recv(acceptd, &msg, sizeof(MSG), 0) > 0)
	{
		switch(msg.type)
		{
			case R:
				do_register(acceptd, &msg, db);
				break;
			case L: 
				do_login(acceptd, &msg, db);
				break;
			case D:
				do_delect_usr(acceptd, &msg, db);
				break;
			case C:
				do_change_usr(acceptd, &msg, db);
				break;
			case S:
				do_search(acceptd, &msg, db);
				break;
			case H:
				do_change_passwd(acceptd, &msg, db);
				break;
		}
	
	}
}

int main(int argc, const char *argv[])
{
	int socketd, acceptd;

	struct sockaddr_in serveraddr;
	pid_t pid;
	MSG msg;
	sqlite3 *db;
	if(argc < 3){
		printf("ip port input error\n");
		exit(-1);
	}

	//打开数据库
	//在数据库中创建两个表一个负责用户名和密码一个负责历史记录
	//
	if(sqlite3_open(DATABASE, &db) != SQLITE_OK){
	printf("error open sqlite3\n");
	return -1;
	}


	//创建套接字
	if((socketd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
		perror("fail to socket");
		exit(-1);
	}

	//填充网络结构体
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
	serveraddr.sin_port = htons(atoi(argv[2]));
	
	//绑定网络结构体和套接字
	if(bind(socketd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0){
	perror("bind error");
	return -1;
	}
	
	//监听套接字
	//
	if(listen(socketd, 5) < 0){
	perror("listen error");
	exit(-1);
	}	

	signal(SIGCHLD, SIG_IGN);

	while(1){
	
		if((acceptd = accept(socketd, NULL, NULL)) < 0){
		
			perror("accept error");
			exit(-1);
		}

		if((pid = fork()) < 0){
		
			perror("fork error");
			exit(-1);
		}
		if(pid == 0)
		{
			do_client(acceptd, db);
		}
		close(acceptd);
	}

	return 0;
}


